#ifndef _SYS_CONTROLLER_H
#define _SYS_CONTROLLER_H

#include <QString>
#include <QStringList>

class ProgramManager;

// TODO: aaaaa... seems that we should provide GetDevList(), GetXXX() and so
// on to prevent UI module touch the TableDriver.
// If not, there is no need to do convertions in this class, just leave it
// to the UI module, I need do much more research on this topic!
class SysController {
public:
	static SysController *instance();

	QStringList ItemsList() const;
	QStringList DevicesList() const;
	QStringList FilterOptList() const;
	QStringList ChannelList() const;
	QStringList OnOffList() const;
	QStringList ItemRangeList(int item_index, bool bias) const;

	bool IsMasterItem(int item_index) const;
	bool IsEsdItem(int item_index) const;
	bool IsDlmItem(int item_index) const;

	// type:
	// 1 = item wait time
	// 2 = item vol limit
	// NOTE!: I should use a enum, but now I have no time, fix later
	double RangeUpper(int type) const;
	double RangeLower(int type) const;
	double RangeStep(int type) const;
	bool IsRangeInteger(int type) const;

	// 3 - hue rng
	// 4 - hue scf
	QStringList RangeList(int type) const;
	
	double ItemRangeUpper(int item_index, bool bias) const;
	double ItemRangeLower(int item_index, bool bias) const;
	double ItemRangeStep(int item_index, bool bias) const;
	bool IsItemRangeInteger(int item_index, bool bias) const;

	int LoadProgram(const QString &path);
	int SaveProgram(const QString &path);
	void NewProgram();

	QString programFilePath() const;

	bool IsProgramDirty() const;

	int InsertItem(int item_index, const QString& item_name);
	int RemoveItem(int item_index);

	int setDeviceType(const QString& dev_name);
	QString deviceType() const;

	int itemCount() const;

	// MEASURE OPTIONS

	int setMeasOptMeasMode(const QString& meas_mode);
	QString measOptMeasMode() const;
	int setMeasOptFfs(bool enable);
	bool measOptFfs() const;
	int setMeasOptCntClr(bool enable);
	bool measOptCntClr() const;
	// TODO: this setting will decide whether save result data or not,
	// think about it, and make a good design...
	int setMeasOptDataFile(bool enable);
	bool measOptDataFile() const;

	// these functions do convertions between string and numbers,
	// that means, all string returned is formatted by range's dfmt
	// TODO: should it be done by the UI module itself?
	// DO NOT let the UI module know about TableDriver, so I think it's OK
	
	int setOptEndTime(const QString& end_time);	
	QString optEndTime() const;
	int setOptOffTime(const QString& off_time);
	QString optOffTime() const;
	int setOptWarnNgCnt(const QString& warn_ng_cnt);
	QString optWarnNgCnt() const;
	int setOptFilterFreq(const QString& fil_freq);
	QString optFilterFreq() const;
	int setOptHdrLogic(const QString& hdr_logic);
	QString optHdrLogic() const;
	int setOptDlmCoef(const QString& coef);
	QString optDlmCoef() const;
	int setOptSelStep(bool enable);
	bool optSelStep() const;

	int changeItemChannel(int item_index);
//	int setItemNameChnSuffix(int item_index, const QString& item_ch_sfx);
	bool ItemHasDetail(int item_index) const;
	int setItemChannel(int item_index, const QString& item_ch_sfx);
	int setItemChannelEx(int item_index, const QString& ch);
	QString itemChannel(int item_index) const;
	QString	itemNameChnSuffix(int item_index) const;
	int setItemWaitTime(int item_index, const QString& wait_time);
	QString itemWaitTime(int item_index) const;	
	int setItemBiasRng(int item_index, const QString& rng_name);
	QString itemBiasRng(int item_index) const;
	int setItemBiasVal(int item_index, const QString& val);
	QString itemBiasVal(int item_index) const;
	QString itemBiasValUnit(int item_index) const;
	int setItemMeasRng(int item_index, const QString& rng_name);
	QString itemMeasRng(int item_index) const;
	// lower - set lower or upper
	int setItemMeasVal(int item_index, bool lower, const QString& val);
	QString itemMeasVal(int item_index, bool lower) const;
	QString itemMeasValUnit(int item_index) const;
	int setItemFilterOpt(int item_index, const QString &fil_opt);
	QString itemFilterOpt(int item_index);
//	int changeItemFilterOpt(int item_index);
	int setItemVolLimit(int item_index, const QString& limit); 
	QString itemVolLimit(int item_index) const;
	int setItemLimitJudge(int item_index, const QString& onoff);
	QString itemLimitJudge(int item_index) const;
	int changeItemLimitJudge(int item_index);

	QStringList RefItemList(int item_index) const;

	// set esd[ref_idx]
	int setEsdRefItem(int itm_idx, int ref_idx, const QString& item_ch_sfx);	
	// TODO: how about the following one? think...
//	int setEsdRefItem(int itm_idx, int ref_idx, 
//					  const QString& item_name, int ch, char suffix);
	// return esd[ref_idx] item's NAME-CHANNEL-SUFFIX string
	QString esdRefItem(int itm_idx, int ref_idx) const;

	int setHueAutoRange(int item_index, bool enable);
	bool hueAutoRange(int item_index) const;
	int setHueOfstCancel(int item_index, bool enable);
	bool hueOfstCancel(int item_index) const;
	int setHuePreAmpRng(
			int item_index, int pre_amp_idx, const QString& rng_name);
	QString huePreAmpRng(int item_index, int pre_amp_idx) const;
	int setHueAmpScf(int item_index, int amp_idx, const QString& scf_name);
	QString hueAmpScf(int item_index, int amp_idx) const;
	

private:
	static const int kValStrLenMax = 10;

	SysController();
	QString FormatValueString(ushort rng_code, double value) const;

	static SysController *instance_;
	
	ProgramManager *pm_;
};


#endif // _SYS_CONTROLLER_H
